iT邦幫忙

2022 iThome 鐵人賽

DAY 3
0
Modern Web

每日任務 Vue 起來系列 第 3

每日任務 Vue 起來 Day 3. JavaScript 回顧 (2)

  • 分享至 

  • xImage
  •  

來到我們文章的第三天,看著小任務的題目們,今天看起來就是繼續回顧了 ( 喂!

▸ 物件參考

這兩個小任務需要參考 JavaScript 的「淺拷貝」與「深拷貝」的觀念。這邊簡單說明一下:

淺拷貝是共用同一個記憶體空間,因此當有一方改變,另一方也會一起改變;深拷貝則是直接拷貝位址,因此是兩個不同的記憶體空間,無法改變原先的程式碼狀態。

任務

1-1. 請問以下的輸出結果為何?

let obj = {
    title: '錢錢',
    amounts: 66666,
}
let objNew = obj;
objNew.amounts = 123;
console.log(obj.amounts); // 輸出結果為何? 
console.log(obj === objNew); // 輸出結果為 true 還是 false?

以輸出結果來看,很明顯是做了淺拷貝,當 objNew.amounts = 123; 的時候,obj.amounts 也一併被改變,他們共用同一個記憶體空間。

123
true

1-2. 如果希望 console.log(obj === objNew); 的結果為 false,則可以如何修改?

let obj = {
    title: '錢錢',
    amounts: 66666,
}
let objNew = { ...obj };
// 或 let objNew = Object.assign({}, obj);
objNew.amounts = 123;
console.log(obj.amounts); // 輸出結果為何? 
console.log(obj === objNew); // 輸出結果為 true 還是 false?

使用 ES6 的功能 operator,利用 …obj 的方式展開,使 obj 只有一層的情況時成為深拷貝,於是輸出以下結果:

66666
false

任務 ② ****( 陷阱題,需要用深拷貝處理 )

2-1. 請問以下的輸出結果為何?

let obj = {
    title: '錢錢',
    amounts: 66666,
    innerObj: {
    	title: '私房錢',
      amounts: 1000
    }
}
let objNew = {...obj};
console.log(obj === objNew); // 輸出結果為 true 還是 false?
objNew.innerObj.amounts = 2000;
console.log(obj.innerObj.amounts); // 輸出結果為何?
false
2000

上面的註解有說到,深拷貝是直接拷貝位址,所以在不同記憶體空間的情況下,照理來說我們應該是無法修改 objNew.innerObj.amounts,但為什麼還是改到了?因為這種展開方式只會複製表層而已,如果物件超過一層,深層的內容仍然是共用同一個記憶體。

這裡也給大家介紹一下 Object.assign(target, source),他的作用是將來源的 object 分派給指定的物件,但是以下面的結果來看,他仍然無法做最全面的深拷貝,因此在這邊我覺得就是知道一下有這個東西就可以了。

let obj = {
    title: '錢錢',
    amounts: 66666,
    innerObj: {
    	title: '私房錢',
      amounts: 1000
    }
}
let objNew = Object.assign({}, obj);
console.log(obj === objNew); // 輸出結果為 true 還是 false?
objNew.innerObj.amounts = 2000;
console.log(obj.innerObj.amounts); // 輸出結果為何?
false
2000

2-2. 如果希望調整 objNew.innerObj 時不會影響到 obj,則可以如何修改?

let obj = {
    title: '錢錢',
    amounts: 66666,
    innerObj: {
    	title: '私房錢',
      amounts: 1000
    }
}
let objNew = JSON.parse(JSON.stringify(obj))
console.log(obj === objNew); // 輸出結果為 true 還是 false?
objNew.innerObj.amounts = 2000;
console.log(obj.innerObj.amounts); // 輸出結果為何?

真正的深拷貝方法終於出現了XD,使用 JSON.stringify(obj) 以及 JSON.parse(JSONString),將物件轉成字串再轉成物件,便可以確保出來一個新的物件,且不同的記憶體位置。

false
1000

▸ 程式錯誤發現

任務:

  1. 請修正以下程式碼錯誤,並執行 console.log
  2. 請嘗試說明以下程式碼錯誤的原因
let saySomething = '小姐一個人嗎 :D'
(function() {
  console.log(saySomething);
});

以上程式碼執行之後會回傳:

"小姐一個人嗎 :D" is not a function

這是因為運行時,被認為是同一行,像這樣:

let saySomething = '小姐一個人嗎 :D'(function() {
  console.log(saySomething);
});
  1. ' 小姐一個人嗎 :D ' 這一段被當成函式來運行,只要在後面加一個分號就能正常運行了。
  2. 立即函式需要在結尾加入一組 ( ) 才會正確執行。

對於分號加或不加的部分,自己比較沒有那個疑慮,因為我是分號魔人 ( ? ),真的很愛一結束就來個分號。

▸ const 特性

任務:

let name = '小明';
const age = 16;
let person = {
  name: '小明',
}
const wallet = {
  money: 1000
}
const dessert = ['cake', 'ice-cream'];

/* 請問以下程式碼哪些會報錯? */
name = '小美';
age = 17;
person.name = '大明';
wallet.money = 1100;
wallet = {};
dessert.push('fruit');
dessert = ['chocolate'];
// 以下三個錯誤回報原因皆為 const 不能重新賦予
age
wallet = {};
dessert = ['chocolate'];

▸ 箭頭函式

任務:

請將以下程式碼簡化為箭頭函式 ( 不影響結果的情況下進行最大簡化 )

// 題目一
function sum(a, b) {
  let c = a + b;
  return c;
}
console.log(sum(5, 6));

// 題目二
function square(num) {
  return num * num;
}
console.log(square(5))

// 題目三
setTimeout(function() {
  console.log('延遲 1 秒');
}, 1000);

// 題目四
let arr = [1, 2, 3];
let arrNew = arr.map(function(item, i) {
  return item * i;
});
console.log(arrNew);

// 題目五
let obj = {
  fn: function fn2(a) {
    return a * a;
  }
}
console.log(obj.fn(10));

解答:

// 題目一
const sum = (a, b) => {
	let c = a + b;
	return c
}
console.log(sum(5, 6));

// 題目二
const square = num => num * num;
console.log(square(5))

// 題目三
setTimeout(() => {
	console.log('延遲 1 秒');
}, 1000);

// 題目四
let arr = [1, 2, 3];
let arrNew = arr.map((item, i) => item * i);
console.log(arrNew);

// 題目五
let obj = {
  fn: a => a * a
}
console.log(obj.fn(10));

▸ 解構賦值和其餘運算子

任務 ① ****依據提示將以下程式碼用解構方式達成目標

// 題目一: 請使用解構,取出 name 及 age 的變數
const person = {
  name: '小明',
  age: 16
}
console.log(name, age); 

// 題目二: 請問以下 console.log 的輸出結果為何?
let [a, b, c = 4, d = 'New', e] = [1, 2, 3];
console.log(a, b, c, d, e);

解答:

// 題目一
const { name, age } = person;
console.log(name, age); // 小明 16
// 題目二
let [a, b, c = 4, d = 'New', e] = [1, 2, 3];
// a 是被右邊賦值 1,b 被右邊賦值 2,c 被右邊賦值 3,d 新增並賦值 'New'
// e 沒有任何東西所以是 undefined
console.log(a, b, c, d, e); // 1, 2, 3, 'New', undefined

任務 ② ****依據提示將以下程式碼用展開方式達成目標

// 題目一: 請使用展開將 arr 的內容併入 arrNew
let arr = [1, 2, 3];
let arrNew = [?, 4, 5, 6]; 
console.log(arrNew);

// 題目二: 請使用展開將 restInfo 的內容併入 MingInfo
let restInfo = {
  sex: '男生',
  height: 178
}
let MingInfo = {
  name: '小明',
  age: 20,
}

解答:

// 題目一
let arr = [1, 2, 3];
let arrNew = [...arr, 4, 5, 6];
console.log(arrNew); // [1, 2, 3, 4, 5, 6]
// 題目二
let restInfo = {
  sex: '男生',
  height: 178
}
let MingInfo = {
  name: '小明',
  age: 20,
	...restInfo
}
console.log(MingInfo); // {name: '小明', age: 20, sex: '男生', height: 178}

任務 ③ ****請修改以下程式碼,透過參數預設值、其餘參數的方式完成此範例。

function getMoney(/* 填入程式碼 */) {
  return money;
}
let myMoney = getMoney();

// fruits 是一個陣列
function buySomething(/* 填入程式碼 */) {
  if(fruits.length > 2) {
    myMoney -= 200;
  }else {
    myMoney -= 100;
  }
  console.log(`小明剩下 ${myMoney} 元`);
}
buySomething('lemon', 'watermelon', 'kiwi');
buySomething('lemon', 'watermelon');

解答:

function getMoney(money = 500) {
  return money;
}
let myMoney = getMoney();

// 展開代入一個陣列
function buySomething(...fruits) {
  if(fruits.length > 2) {
    myMoney -= 200;
  }else {
    myMoney -= 100;
  }
  console.log(`小明剩下 ${myMoney} 元`);
}
buySomething('lemon', 'watermelon', 'kiwi'); // 結果為 "小明剩下 300 元"
buySomething('lemon', 'watermelon'); // 結果為 "小明剩下 400 元"

有關 JavaScript 的回顧小任務就到今天,明天開始就讓我們一起練習 bootstrap 語法的運用吧,當然對這些語法已經熟到不能再熟的朋友們,也可以直接跳過這幾天了(笑

那麼夜已深,晚安了各位。


上一篇
每日任務 Vue 起來 Day 2. JavaScript 回顧 (1)
下一篇
每日任務 Vue 起來 Day 4. 開發好幫手 Bootstrap
系列文
每日任務 Vue 起來12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言